package com.aispeech.astools.view;

import android.graphics.PixelFormat;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.text.TextUtils;
import android.util.Log;
import android.view.ViewTreeObserver;
import android.widget.TextView;

import com.aispeech.astools.ASTApplication;
import com.aispeech.astools.R;
import com.aispeech.astools.utils.AudioFileWrite;
import com.aispeech.audiowavelib.draw.WaveCanvas;
import com.aispeech.audiowavelib.view.WaveSurfaceView;
import com.aispeech.providerlib.engine.AIEngineType;
import com.aispeech.providerlib.engine.AiProviderEngine;
import com.aispeech.providerlib.engine.EngineException;
import com.aispeech.providerlib.engine.EngineListener;
import com.aispeech.providerlib.utils.PrvdLibConstants;

import java.io.File;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import androidx.appcompat.app.AppCompatActivity;
import androidx.viewpager.widget.ViewPager;

public class RemoteRecordActivity extends AppCompatActivity {
    private final String TAG = "RemoteRecordActivity";

    private static final int MSG_ADD_DEV = 1;
    private static final int MSG_REMOVE_DEV = 2;
    private static final int MSG_CLEAN_DEV = 3;
    private static final int MSG_SHOW_MESSAGE = 4;
    private static final int MSG_DRAW_AUDIO_WAVE = 5;


    private TextView mTvInfo;
    private ViewPager mVPDevInfo;
    private CardPagerAdapter mCardAdapter;
    private ShadowTransformer mCardShadowTransformer;
    private WaveSurfaceView mWaveSfv;
    private WaveCanvas mWaveCanvas;

    private AiProviderEngine mProviderEngine;
    private AudioFileWrite mAfileWrite;
    private int mSupportEngine = AIEngineType.ENGINE_USB;

    private String externalStorageDirectory = Environment.getExternalStorageDirectory().getAbsolutePath();
    private String AudioOnBufPath = externalStorageDirectory + File.separator + "tcr" + File.separator ;//+ "onbuf.pcm";

    private Set<String> mRemoteDevSet;
    private Map<String, String> mDevNameInfoMap;

    private Handler mHandler;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_remote_record);

        initHandler();
        initData();
        initView();
        initEngine();
    }

    private void initHandler() {
        mHandler = new Handler(getMainLooper()) {
            @Override
            public void handleMessage(Message msg) {
                super.handleMessage(msg);
                Log.d(TAG, "handleMessage: " + msg.what);
                switch (msg.what) {
                    case MSG_ADD_DEV:
                        String id = (String) msg.obj;
                        addDevice(id);
                        break;
                    case MSG_REMOVE_DEV:
                        removeDevice((String) msg.obj);
                        break;
                    case MSG_CLEAN_DEV:
                        cleanDevice();
                        break;
                    case MSG_SHOW_MESSAGE:
                        mTvInfo.setText((String) msg.obj);
                        break;
                    case MSG_DRAW_AUDIO_WAVE:
                        byte[] buf = (byte[]) msg.obj;
                        if (null != mWaveCanvas) {
                            mWaveCanvas.startDraw(buf);
                        }
                        break;
                }
            }
        };
    }

    private void initData() {

        mDevNameInfoMap = new HashMap<>();
        mDevNameInfoMap.put("30021:20001", "nano");
        mDevNameInfoMap.put("4310:45830", "boxin");
        mDevNameInfoMap.put("36705:63540", "boguan");
        mDevNameInfoMap.put("4310:45063", "juxin");

        mRemoteDevSet = new HashSet<>();
    }

    private void initView() {
        mWaveSfv = findViewById(R.id.aw_audio);
        mWaveSfv.setLineOff(32);
        mWaveSfv.setZOrderOnTop(true);//解决surfaceView黑色闪动效果
        mWaveSfv.getHolder().setFormat(PixelFormat.TRANSLUCENT);
        mWaveSfv.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
            @Override
            public void onGlobalLayout() {
                mWaveSfv.getViewTreeObserver().removeGlobalOnLayoutListener(this);
                //等待view绘制完毕再来启动测试,不然会导致自定义view getHeight() 为0 的情况.
                Log.d(TAG, "onGlobalLayout -- startTest ");
                mWaveCanvas = new WaveCanvas();
                mWaveCanvas.baseLine = mWaveSfv.getHeight() / 2;
                mWaveCanvas.init(mWaveSfv);
            }
        });


        mTvInfo = findViewById(R.id.tv_remote_title);

        mVPDevInfo = findViewById(R.id.vp_dev_info);
        mCardAdapter = new CardPagerAdapter();

//        mCardAdapter.addCardItem(new CardItem(1, 1));

        mCardShadowTransformer = new ShadowTransformer(mVPDevInfo, mCardAdapter);
        mCardShadowTransformer.enableScaling(true);

        mVPDevInfo.setAdapter(mCardAdapter);
        mVPDevInfo.setPageTransformer(false, mCardShadowTransformer);
        mVPDevInfo.setOffscreenPageLimit(3);
        mVPDevInfo.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
            @Override
            public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
//                Log.d(TAG, "onPageScrolled() called with: position = [" + position + "], positionOffset = [" + positionOffset + "], positionOffsetPixels = [" + positionOffsetPixels + "]");
            }

            @Override
            public void onPageSelected(int position) {
                Log.d(TAG, "onPageSelected() called with: position = [" + position + "]");
            }

            @Override
            public void onPageScrollStateChanged(int state) {
//                Log.d(TAG, "onPageScrollStateChanged() called with: state = [" + state + "]");
            }
        });
    }

    private void addDevice(String id) {
        Log.d(TAG, "addDevice: " + id);
        if (null != mCardAdapter) {
            if (!mRemoteDevSet.contains(id)) {
                mRemoteDevSet.add(id);
                mCardAdapter.addCardItem(new CardItem(mDevNameInfoMap.get(id), id));
                mCardAdapter.notifyDataSetChanged();
            }
        }
    }

    private void removeDevice(String id) {
        Log.d(TAG, "removeDevice: ");
        if (null != mCardAdapter) {
            if (mRemoteDevSet.contains(id)) {
                mRemoteDevSet.remove(id);
                mCardAdapter.removeCardItem(id);
                mCardAdapter.notifyDataSetChanged();
            }
        }
    }

    private void cleanDevice() {
        Log.d(TAG, "cleanDevice: ");
        mRemoteDevSet.clear();
        mCardAdapter.cleanCardItem();
        mCardAdapter.notifyDataSetChanged();
    }


    @Override
    protected void onDestroy() {
        super.onDestroy();
        Log.d(TAG, "onDestroy: ");

        destroyEngine();
        mRemoteDevSet.clear();

        if (null != mWaveCanvas) {
            mWaveCanvas.stopDraw();
            mWaveCanvas.destroy();
        }

        if (null != mHandler) {
            mHandler.removeCallbacksAndMessages(null);
        }
    }

    private void destroyEngine() {
        if (null != mProviderEngine) {
            mProviderEngine.destroyEngine();
        }

        if (null != mAfileWrite) {
            mAfileWrite.closeWrite();
        }
    }

    private void initEngine() {
        Log.d(TAG, "initEngine: ------------------- ");
        //write file init
        mAfileWrite = new AudioFileWrite(ASTApplication.getApplication());
        mAfileWrite.startWrite(AudioOnBufPath);

        mProviderEngine = AiProviderEngine.getInstance();
        try {
            mProviderEngine.initEngine(ASTApplication.getApplication(), mSupportEngine, new EngineListener() {
                @Override
                public void onWakeup(int wordIndex, int flag) {
                    Log.d(TAG, "onWakeup() called with: wordIndex = [" + wordIndex + "], flag = [" + flag + "]");
                }

                @Override
                public void onMessage(String topic, String[] args) {
                    try {
                        StringBuilder argsInfo = new StringBuilder();
                        if (null != args) {
                            for (String arg : args) {
                                argsInfo.append(arg + " ");
                            }
                        }
                        Log.d(TAG, "onMessage: " + topic + " args: " + argsInfo.toString());
                        showMsg("onMessage: " + topic + " args: " + argsInfo.toString());
                        switch (topic) {
                            case PrvdLibConstants.MSG_TOPIC_KEY:
                                String keyEvent = args != null ? args[0] : null;
                                if (!TextUtils.isEmpty(keyEvent)) {
                                    if ("0".equals(keyEvent)) {
                                        Log.d(TAG, "onMessage: release key");
                                        //松开
                                    } else if ("1".equals(keyEvent)) {
                                        Log.d(TAG, "onMessage: pass key");
                                        //按下
                                    }
                                }
                                break;
                            case PrvdLibConstants.MSG_TOPIC_DEV_SN:
                                String vid = args != null ? args[0] : null;
                                String pid = (args != null) && args.length > 1 ? args[1] : null;
                                String sn = args != null && args.length > 2 ? args[2] : null;
                                Log.d(TAG, "onMessage: " + topic + " vid = " + vid + " pid = " + pid + " sn = " + sn);
                                break;
                            case PrvdLibConstants.MSG_TOPIC_DEV_VER:
                                String vid2 = args != null ? args[0] : null;
                                String pid2 = args != null && args.length > 1 ? args[1] : null;
                                String ver = args != null && args.length > 2 ? args[2] : null;
                                Log.d(TAG, "onMessage: " + topic + " vid = " + vid2 + " pid = " + pid2 + " ver = " + ver);
                                String id = vid2 + ":" + pid2;
//                                addDevice(new CardItem(mDevNameInfoMap.get(id), id));
                                Message.obtain(mHandler, MSG_ADD_DEV, id).sendToTarget();
                                break;
                            case PrvdLibConstants.MSG_TOPIC_DEV:
                                if ("detached_all".equals(args[0])) {
                                    cleanDevice();
                                    mHandler.sendEmptyMessage(MSG_CLEAN_DEV);
                                }
                                if ("attached".equals(args[0])) {
                                    String vpid = args[1];
                                    Message.obtain(mHandler, MSG_ADD_DEV, vpid).sendToTarget();
                                } else if ("detached".equals(args[0])) {
                                    String vpid = args[1];
                                    Message.obtain(mHandler, MSG_REMOVE_DEV, vpid).sendToTarget();
                                }
                                break;
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }


                @Override
                public void onFarBuffer(byte[] bfBuffer) {
//                    Log.d(TAG, "onFarBuffer with: bfBuffer = " + bfBuffer + "");
                    mAfileWrite.writeBuffer(bfBuffer);
                    drawAudioWave(bfBuffer);
                }

                @Override
                public void onNearBuffer(byte[] bfBuffer) {
//                    Log.d(TAG, "onNearBuffer with: bfBuffer = " + bfBuffer.length + "");
                    mAfileWrite.writeBuffer(bfBuffer);
                    drawAudioWave(bfBuffer);
                }
            });

        } catch (EngineException e) {
            e.printStackTrace();
            mProviderEngine.dump();
        }
    }

    private void showMsg(String s) {
        Log.d(TAG, "showMsg() called with: s = [" + s + "]");
        if (null != mHandler) {
            Message.obtain(mHandler, MSG_SHOW_MESSAGE, s).sendToTarget();
        }
    }

    private void drawAudioWave(byte[] buf) {
        if (null != mHandler) {
            Message.obtain(mHandler, MSG_DRAW_AUDIO_WAVE, buf).sendToTarget();
        }
    }
}
